"""
Flask-APScheduler扩展
用于管理定时任务
"""

from flask_apscheduler import APScheduler
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
from apscheduler.executors.pool import ThreadPoolExecutor
import logging
import importlib

# 创建调度器实例
scheduler = APScheduler()

def init_scheduler(app):
    """初始化调度器"""
    
    # 配置调度器
    class Config:
        SCHEDULER_API_ENABLED = True
        SCHEDULER_TIMEZONE = "Asia/Shanghai"
        
        # 任务存储配置
        SCHEDULER_JOBSTORES = {
            'default': SQLAlchemyJobStore(url=app.config.get('SQLALCHEMY_DATABASE_URI'))
        }
        
        # 执行器配置
        SCHEDULER_EXECUTORS = {
            'default': ThreadPoolExecutor(20),
        }
        
        # 任务默认配置
        SCHEDULER_JOB_DEFAULTS = {
            'coalesce': False,
            'max_instances': 3,
            'misfire_grace_time': 15
        }
    
    app.config.from_object(Config)
    
    # 初始化调度器
    scheduler.init_app(app)
    
    # 启动调度器
    scheduler.start()
    
    # 设置日志
    logging.getLogger('apscheduler').setLevel(logging.INFO)
    
    return scheduler

def get_task_function(func_name):
    """获取任务函数"""
    try:
        # 导入任务模块
        from apps.modules.admin.tasks import TASK_FUNCTIONS
        task_info = TASK_FUNCTIONS.get(func_name)
        if task_info:
            return task_info['func']
        
        # 如果找不到，尝试动态导入
        module = importlib.import_module('apps.modules.admin.tasks')
        if hasattr(module, func_name):
            return getattr(module, func_name)
        
        logging.error(f"找不到任务函数: {func_name}")
        return None
        
    except Exception as e:
        logging.error(f"获取任务函数失败: {e}")
        return None

def add_job_from_task(task):
    """从任务模型添加作业"""
    from apps.modules.admin.models.sys.sys_task import Task
    
    try:
        # 获取任务函数
        func = get_task_function(task.func)
        if not func:
            logging.error(f"任务函数不存在: {task.func}")
            return None
        
        # 解析触发器参数
        import json
        trigger_args = json.loads(task.trigger_args) if task.trigger_args else {}
        
        # 解析args和kwargs
        args = json.loads(task.args) if task.args else []
        kwargs = json.loads(task.kwargs) if task.kwargs else {}
        
        # 添加作业
        job = scheduler.add_job(
            func=func,
            trigger=task.trigger,
            args=args,
            kwargs=kwargs,
            id=task.id,
            name=task.name,
            start_date=task.start_date,
            end_date=task.end_date,
            timezone=task.timezone or 'Asia/Shanghai',
            misfire_grace_time=task.misfire_grace_time or 15,
            coalesce=task.coalesce if task.coalesce is not None else False,
            max_instances=task.max_instances or 3,
            **trigger_args
        )
        
        # 更新下次运行时间
        task.next_run_time = job.next_run_time
        
        logging.info(f"成功添加任务: {task.id} - {task.name}")
        return job
        
    except Exception as e:
        logging.error(f"添加任务失败: {e}")
        return None

def remove_job_from_task(task_id):
    """移除作业"""
    try:
        scheduler.remove_job(task_id)
        logging.info(f"成功移除任务: {task_id}")
        return True
    except Exception as e:
        logging.error(f"移除任务失败: {e}")
        return False

def pause_job_from_task(task_id):
    """暂停作业"""
    try:
        scheduler.pause_job(task_id)
        logging.info(f"成功暂停任务: {task_id}")
        return True
    except Exception as e:
        logging.error(f"暂停任务失败: {e}")
        return False

def resume_job_from_task(task_id):
    """恢复作业"""
    try:
        scheduler.resume_job(task_id)
        logging.info(f"成功恢复任务: {task_id}")
        return True
    except Exception as e:
        logging.error(f"恢复任务失败: {e}")
        return False

def get_job_status(task_id):
    """获取作业状态"""
    try:
        job = scheduler.get_job(task_id)
        if job:
            return {
                'id': job.id,
                'name': job.name,
                'next_run_time': job.next_run_time,
                'enabled': not job.paused
            }
        return None
    except Exception as e:
        logging.error(f"获取任务状态失败: {e}")
        return None

def load_existing_tasks():
    """加载数据库中已存在的任务到调度器"""
    try:
        from apps.modules.admin.models.sys.sys_task import Task
        from apps.extensions import db
        
        # 获取所有启用的任务
        tasks = Task.query.filter_by(enabled=True).all()
        
        for task in tasks:
            try:
                # 检查任务是否已在调度器中
                existing_job = scheduler.get_job(task.id)
                if not existing_job:
                    add_job_from_task(task)
                    logging.info(f"加载任务到调度器: {task.id}")
            except Exception as e:
                logging.error(f"加载任务失败 {task.id}: {e}")
        
        logging.info(f"成功加载 {len(tasks)} 个任务到调度器")
        
    except Exception as e:
        logging.error(f"加载任务失败: {e}")

def init_task_scheduler(app):
    """初始化任务调度器"""
    # 初始化调度器
    init_scheduler(app)
    
    # 加载现有任务
    with app.app_context():
        load_existing_tasks()
    
    return scheduler 